/********************************************************
Project name: OOP - Home Assignment no. 3

Authors: Rami Berkovsky
         Ofir Cohen

File name: Interpreter.cpp

Purpose: Interpreter for assembly-like instructions.
         This file specifies the implementation for the interpreter class.

********************************************************/
#include "Interpreter.h"
#include "Dispatcher.h"
#include "Exceptions.h"
#include <iostream>
#include <fstream>
#include "Parser.h"
#include <vector>
#include <exception>

using namespace std;

// returns a pointer to the instance of Interpreter
Interpreter* Interpreter::getInstance()
{
	if (_instance == 0)
	{
		try {
			_instance = new Interpreter;
			if (_instance == NULL)
				throw MemoryAllocFailed();
		}
		catch (MemoryAllocFailed &e)
		{
			cout << e.what() << endl;
			exit(1);
		}
	}

	return _instance;
}


// starts the process of file interpreting
void Interpreter::startInterpret(const char *filename)
{
	Command *myCmd=NULL;
	ifstream fin(filename);
    string line;
    int line_number=0;

    try
    {
        if (fin.is_open())
	    {
		    while (! fin.eof()) {
                ++line_number;
			    getline(fin,line);
                try {
					RETURN_VALUE ret;
					ret = p.Parse_line(line,fin,DEL_START,&myCmd);
					if (ret == SUCCESS)
						d.Add_command(myCmd);
                }
				catch (MemoryAllocFailed &e)
				{
                    d.Clear_queue();
					cout << e.what() << endl;
					exit(1);
				}
                catch (exception &e)
                {
                    cout << "exception in file: " << filename << endl;
                    cout << "error while reading line " << line_number << ": " << line << endl;
                    cout << e.what() << endl << endl;
					d.Clear_queue();
					return;
				}
		    }
		    // execute all commands
		    d.Execute_command();

		    // print registers after execution
		    cout << filename << " file:" << endl;
            Risc::getInstance().PrintRegisters();
		    cout << endl;

		    // reset all registers to zero
		    Risc::getInstance().ZeroRegisters();
        } else
            throw FileNotFound();
	}
    catch (FileNotFound &e)
    {
        cout << "exception in file: " << filename << endl;
        cout << e.what() << endl << endl;
        return;
    }	
}

// Static member initialization
Interpreter* Interpreter::_instance = 0;
